﻿using Kalman;
using Kalman.Enums;
using System;
using System.Collections.Generic;
using System.Text;

namespace QuDao
{
    /// <summary>
    /// ID生成器配置
    /// </summary>
    public class IDGeneratorOptions
    {
        /// <summary>
        /// 当前机器码（0-255），具体取值范围取决于机器码位数
        /// </summary>
        public byte MachineID { get; set; } = 1;

        /// <summary>
        /// 机器码位数（0-8之间），默认5可以支持32个节点
        /// </summary>
        public byte MachineIDBits { get; set; } = 5;

        /// <summary>
        /// 生成ID的缓存数量，用于防止意外的ID冲突，默认100000
        /// </summary>
        public int CacheCount { get; set; } = 100000;
    }

    /// <summary>
    /// 用于创建业务单据ID（比如订单ID）
    /// </summary>
    public class IDGenerator : SingletonBase<IDGenerator>
    {
        readonly byte machineID = 1; //从配置中读取
        readonly byte machineIDBits = 5; //默认最多支持32个服务器节点
        readonly int cacheCount = 100000;//缓存十万个ID来防止意外ID冲突
        readonly Dictionary<long, DateTime> dic;

        readonly IDWorker idWorkerOfS1024;
        readonly IDWorker idWorkerOfS4096;
        readonly IDWorker idWorkerOfS32768;
        readonly IDWorker idWorkerOfM1024;
        readonly IDWorker idWorkerOfM4096;
        readonly IDWorker idWorkerOfH4096;
        readonly IDWorker idWorkerOfH1024;
        readonly IDWorker idWorkerOfH256;
        readonly IDWorker idWorkerOfMS1024;

        public IDGenerator() : base()
        {
            var options = AppConfig.Instance.GetSection<IDGeneratorOptions>("IDGenerator");
            if (options != null)
            {
                machineID = options.MachineID;
                machineIDBits = options.MachineIDBits;
                cacheCount = options.CacheCount;
            }

            //部署时通过配置读取机器ID
            idWorkerOfS1024 = new IDWorker(TimePrecision.Second, machineID, machineIDBits, 10);//每秒最多可以生成1024个订单ID
            idWorkerOfS4096 = new IDWorker(TimePrecision.Second, machineID, machineIDBits, 12);//每秒最多可以生成4096个订单ID
            idWorkerOfS32768 = new IDWorker(TimePrecision.Second, machineID, machineIDBits, 15);//每秒最多可以生成32768个订单ID
            idWorkerOfM1024 = new IDWorker(TimePrecision.Minute, machineID, machineIDBits, 10);//每分钟最多可以生成1024个订单ID
            idWorkerOfM4096 = new IDWorker(TimePrecision.Minute, machineID, machineIDBits, 12);//每分钟最多可以生成4096个订单ID
            idWorkerOfH256 = new IDWorker(TimePrecision.Hour, machineID, machineIDBits, 8);//每小时最多可以生成256个订单ID
            idWorkerOfH1024 = new IDWorker(TimePrecision.Hour, machineID, machineIDBits, 10);//每小时最多可以生成1024个订单ID
            idWorkerOfH4096 = new IDWorker(TimePrecision.Hour, machineID, machineIDBits, 12);//每小时最多可以生成4096个订单ID
            idWorkerOfMS1024 = new IDWorker(TimePrecision.Millisecond, machineID, machineIDBits, 10);//每毫秒秒最多1024个ID

            dic = new Dictionary<long, DateTime>();
        }

        /// <summary>
        /// 判断生成的ID是否有冲突，如果无冲突将新生成的ID加入字典
        /// </summary>
        /// <param name="id">新生成的ID</param>
        /// <returns>无冲突返回true，否则返回false</returns>
        bool CheckOrAdd(long id)
        {
            if (dic.Count > cacheCount) //
            {
                dic.Clear();
                dic.Add(id, DateTime.Now);
                return true;
            }

            if (dic.ContainsKey(id))
            {
                return false;
            }
            else
            {
                dic.Add(id, DateTime.Now);
                return true;
            }
        }

        long GetID(IDWorker worker)
        {
            while (true)
            {
                var id = worker.NewID();
                if (!CheckOrAdd(id)) continue;
                return id;
            }
        }

        /// <summary>
        /// 获取ID（每秒最多1024个ID）
        /// </summary>
        /// <returns></returns>
        public long GetIDByS1024() => GetID(idWorkerOfS1024);

        /// <summary>
        /// 获取ID（每秒最多4096个ID）
        /// </summary>
        /// <returns></returns>
        public long GetIDByS4096() => GetID(idWorkerOfS4096);

        /// <summary>
        /// 获取ID（每秒最多32768个ID）
        /// </summary>
        /// <returns></returns>
        public long GetIDByS32768() => GetID(idWorkerOfS32768);

        /// <summary>
        /// 获取ID（每分钟最多1024个ID）
        /// </summary>
        /// <returns></returns>
        public long GetIDByM1024() => GetID(idWorkerOfM1024);

        /// <summary>
        /// 获取ID（每分钟最多4096个ID）
        /// </summary>
        /// <returns></returns>
        public long GetIDByM4096() => GetID(idWorkerOfM4096);

        /// <summary>
        /// 获取ID（每小时最多256个ID）
        /// </summary>
        /// <returns></returns>
        public long GetIDByH256() => GetID(idWorkerOfH256);

        /// <summary>
        /// 获取ID（每小时最多1024个ID）
        /// </summary>
        /// <returns></returns>
        public long GetIDByH1024() => GetID(idWorkerOfH1024);

        /// <summary>
        /// 获取ID（每小时最多4096个ID）
        /// </summary>
        /// <returns></returns>
        public long GetIDByH4096() => GetID(idWorkerOfH4096);

        /// <summary>
        /// 获取ID（每毫秒秒最多1024个ID）
        /// </summary>
        /// <returns></returns>
        public long GetIDByMS1024() => GetID(idWorkerOfMS1024);

        public string GetFileID()
        {
            var id = IDGenerator.Instance.GetIDByM4096() * 10 + RandomUtil.GetInteger(0, 9);
            return id.ToString();
        }

    }
}
